
package com.huawei.saashousekeeper.config;

import com.huawei.saashousekeeper.interceptor.FeignRequestInterceptor;
import com.huawei.saashousekeeper.interceptor.MybatisInterceptor;
import com.huawei.saashousekeeper.interceptor.RabbitMqAspect;
import com.huawei.saashousekeeper.interceptor.TenantDomainFilter;

import lombok.extern.log4j.Log4j2;

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Optional;

/**
 * 自动装配
 *
 * @since 2022-02-14
 */
@Configuration
@EnableConfigurationProperties(value = TenantConfigurer.class)
@Log4j2
@ConditionalOnProperty(prefix = "spring.schema", name = "enabled", havingValue = "true")
public class TenantAutoConfiguration {

    /**
     * mybatis拦截器
     *
     * @return mybatis拦截器
     */
    @Bean
    public MybatisInterceptor mybatisInterceptor() {
        return new MybatisInterceptor();
    }

    /**
     * feign调用传递租户标识
     *
     * @return
     */
    @Bean
    public FeignRequestInterceptor feignRequestInterceptor() {
        return new FeignRequestInterceptor();
    }

    /**
     * MQ消息接收时保存租户标识
     *
     * @return AOP切面
     */
    @Bean
    public RabbitMqAspect rabbitMqAspect() {
        return new RabbitMqAspect();
    }

    /**
     * MQ消息发送时传递租户标识
     *
     * @param factory
     * @return RabbitTemplate
     */
    @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory factory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(factory);

        // 消息发送前保存租户标识
        rabbitTemplate.setBeforePublishPostProcessors(new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                String tenantDomain = TenantContext.get();
                log.info("发送消息前的tenantDomain : " + tenantDomain);
                // 消息发送前保存租户标识
                Optional.ofNullable(tenantDomain)
                    .ifPresent(domain -> message.getMessageProperties().setHeader("tenantDomain", tenantDomain));
                return message;
            }
        });
        return rabbitTemplate;
    }

    /**
     * 租户标识过滤器
     *
     * @return TenantDomainFilter
     */
    @Bean
    public TenantDomainFilter tenantDomainFilter() {
        return new TenantDomainFilter();
    }
}
